package com.threeti.mecool.framework.util;

import java.io.Serializable;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;


/**
 * 分页集合处理类
 *
 *  @author Jay Meng
 *
 */
public class PagedListHandler<T extends Object> implements Serializable {
  public static final PagedListHandler EMPTY_LIST = new PagedListHandler(Collections.EMPTY_LIST, 0, 0, 0);
  public static final int DEFAULT_PAGE_SIZE = 10;
  public static final int DEFAULT_PAGE_AREA_SIZE = 5;

  /** 结果集的总记录条数 */
  private int totalSize;

  /** 结果集的总页数 */
  private int totalPage;

  /** 单页记录条数*/
  private int pageSize = DEFAULT_PAGE_SIZE;

  /** 目标页的起始记录索引 */
  private int startingIndex;

  /** 目标单页(注意，非整个集合)的搜索结果集合 */
  private List<T> pageList;

  private int page = 0;

  private boolean newPageSet;

  private boolean hasNextPageArea;
  private boolean hasPreviousPageArea;

  public PagedListHandler(List<T> pageList, long totalSize, int page, int startingIndex) {
    this.pageList = pageList;
    this.totalSize = (int)totalSize;
    this.page = page;
    this.startingIndex = startingIndex;
    this.totalPage = getPageCount();
  }

  public void setPageList(List<T> pageList) {
    this.pageList = pageList;
    //this.refreshDate = new Date();
  }

  public int getPageSize() {
    return pageSize;
  }

  public int getStartingIndex() {
    return startingIndex;
  }

  public long getTotalSize() {
    return totalSize;
  }

  public boolean isFirstPage() {
    return getPage() == 0;
  }

  public boolean isLastPage() {
    return getPage() == getPageCount() -1;
  }

  public List<T> getPageList() {
    return pageList;
  }

  public void setPage(int page) {
    this.page = page;
    this.newPageSet = true;
  }

  public int getPage() {
    this.newPageSet = false;
    if (this.page >= getPageCount()) {
      this.page = getPageCount() - 1;
    }
    return this.page;
  }

  public int getPageCount() {
    float numOfPages = (float) totalSize / getPageSize();
    return (int) ((numOfPages > (int) numOfPages || numOfPages == 0.0) ? numOfPages + 1 : numOfPages);
  }
  
  public void setPageSize(int pageSize) {
    if (pageSize != this.pageSize) {
      this.pageSize = pageSize;
      if (!this.newPageSet) {
        this.page = 0;
      }
    }
  }

  public void previousPage() {
    if (!isFirstPage()) {
      this.page--;
      startingIndex -= pageSize;
    }
  }

  public void nextPage() {
    if (!isLastPage()) {
      this.page++;
      startingIndex += pageSize;
    }
  }

  /**
   * return the page show area of the specified page
   * ex:areaSize = 4 curPage =2 page show area:1,2,3,4
   */
  public int[] getPageShowArea(int currentPage) {
    return getPageShowArea(DEFAULT_PAGE_AREA_SIZE, currentPage);
  }

  public int[] getPageShowArea(int areaSize, int currentPage) {
    if (currentPage <= 0) return null;
    if (currentPage > totalPage) {
      currentPage = totalPage;
    }
    if (areaSize <= 0) return null;
    if (areaSize > totalPage) {
      areaSize = totalPage;
    }
    int[] pageArea = new int[areaSize];
    int perMaxValueInArea = 0;

    if (this.totalPage % areaSize == 0) {
      int areaCount = this.totalPage / areaSize;
      for (int i = 1; i <= areaCount; i++) {
        perMaxValueInArea = i * areaSize;

        if (currentPage <= perMaxValueInArea) {
          for (int j = 0; j < areaSize; j++) {
            pageArea[j] = perMaxValueInArea--;
          }
          break;
        } else {
          continue;
        }
      }
    } else {
      int areaCount = this.totalPage / areaSize + 1;
      for (int i = 1; i <= areaCount; i++) {
        perMaxValueInArea = i * areaSize;
        if (i == areaCount) perMaxValueInArea = this.totalPage;
//        if (i == areaCount) {
//          int lastAreaSize = this.totalPage % areaSize;
//          perMaxValueInArea = this.totalPage;
//          areaSize = lastAreaSize;
//        }
        if (currentPage <= perMaxValueInArea) {
          for (int j = 0; j < areaSize; j++) {
            pageArea[j] = perMaxValueInArea--;
          }
          break;
        } else {
          continue;
        }
      }
    }
    Arrays.sort(pageArea);
    perMaxValueInArea = pageArea[areaSize - 1];
    int perMinValueInArea = pageArea[0];

    hasNextPageArea =  totalPage > perMaxValueInArea;
    hasPreviousPageArea = (perMinValueInArea != 1);

    return pageArea;
  }
  public boolean hasPreviousPageArea() {
    return hasPreviousPageArea;
  }

  public boolean hasNextPageArea() {
    return hasNextPageArea;
  }
}

